home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / utils / djtarx.c < prev    next >
C/C++ Source or Header  |  1994-06-27  |  8KB  |  356 lines

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys/stat.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <dos.h>
  7. #include <time.h>
  8. #include <io.h>
  9.  
  10. #include "oread.h"
  11.  
  12. void Fatal(char *msg)
  13. {
  14.   fprintf(stderr, "Fatal! %s!\n", msg);
  15.   exit(1);
  16. }
  17.  
  18. /*------------------------------------------------------------------------*/
  19.  
  20. typedef struct CE {
  21.   struct CE *next;
  22.   char *from;
  23.   char *to;
  24. } CE;
  25.  
  26. #define HASHSIZE 2048
  27. #define HASHMASK 2047
  28. #define HASHBITS 11
  29. CE *htab[HASHSIZE];
  30.  
  31. unsigned long hash(unsigned char *cp)
  32. {
  33.   unsigned long rv = 0;
  34.   while (*cp)
  35.     rv += *cp++;
  36.   while (rv > HASHMASK)
  37.     rv = (rv & HASHMASK) + (rv >> HASHBITS);
  38.   return rv;
  39. }
  40.  
  41. void store_entry(char *from, char *to)
  42. {
  43.   unsigned long h = hash(from);
  44.   CE *ce = (CE *)malloc(sizeof(CE));
  45.   if (ce == 0)
  46.     Fatal("Out of memory");
  47.   ce->from = strdup(from);
  48.   ce->to = strdup(to);
  49.   ce->next = htab[h];
  50.   htab[h] = ce;
  51. }
  52.  
  53. char *get_entry(char *from)
  54. {
  55.   CE *ce;
  56.   for (ce = htab[hash(from)]; ce; ce=ce->next)
  57.   {
  58.     if (strcmp(ce->from, from) == 0)
  59.       return ce->to;
  60.   }
  61.   return from;
  62. }
  63.  
  64. void DoNameChanges(char *fname)
  65. {
  66.   FILE *f = fopen(fname, "r");
  67.   char from[100], to[100];
  68.   char line[250];
  69.   if (f == 0)
  70.   {
  71.     perror(fname);
  72.     exit(1);
  73.   }
  74.   while (1)
  75.   {
  76.     fgets(line, 250, f);
  77.     if (feof(f))
  78.       break;
  79.     to[0] = 0;
  80.     sscanf(line, "%s %s", from, to);
  81.     if (to[0])
  82.       store_entry(from, to);
  83.   }
  84.   fclose(f);
  85. }
  86.  
  87. /*------------------------------------------------------------------------*/
  88.  
  89. FILE *change_file;
  90.  
  91. int v_switch = 0;
  92.  
  93. main(int argc, char **argv)
  94. {
  95.   int i = 1;
  96.   if (argc < 2)
  97.   {
  98.     fprintf(stderr, "djtarx [-n changeFile] [-v] tarfile . . .\n");
  99.     exit(1);
  100.   }
  101.   while ((argc > i) && (argv[i][0] == '-'))
  102.   {
  103.     switch (argv[i][1])
  104.     {
  105.       case 'n':
  106.         DoNameChanges(argv[i+1]);
  107.         i++;
  108.         break;
  109.       case 'v':
  110.         v_switch = 1;
  111.         break;
  112.     }
  113.     i++;
  114.   }
  115.   for (; i < argc; i++)
  116.     tarread(argv[i]);
  117.   change_file = fopen("/tarchange.lst", "w");
  118.   dump_changes();
  119.   fclose(change_file);
  120. }
  121.  
  122. /*------------------------------------------------------------------------*/
  123.  
  124. typedef struct CHANGE {
  125.   struct CHANGE *next;
  126.   char *old;
  127.   char *new;
  128.   int isdir; /* 0=file, 1=dir, 2=skip */
  129. } CHANGE;
  130.  
  131. CHANGE *change_root = 0;
  132.  
  133. dump_changes()
  134. {
  135.   CHANGE *c;
  136.   for (c=change_root; c; c=c->next)
  137.     fprintf(change_file, "%s -> %s\n", c->old, c->new);
  138. }
  139.  
  140. int change(char *fname, char *problem, int isadir)
  141. {
  142.   CHANGE *ch;
  143.   char new[200];
  144.   char *pos, *info;
  145.  
  146.   for (ch=change_root; ch; ch = ch->next)
  147.     if ((strncmp(fname, ch->old, strlen(ch->old)) == 0) && ch->isdir)
  148.     {
  149.       if (ch->isdir == 2)
  150.       {
  151.         printf("  [ skipping %s ]\n", fname);
  152.         return 0;
  153.       }
  154. /*      printf("  [ changing %s to ", fname); */
  155.       sprintf(new, "%s%s", ch->new, fname+strlen(ch->old));
  156.       strcpy(fname, new);
  157. /*      printf("%s ]\n", fname); */
  158.       return 1;
  159.     }
  160.   info = strstr(fname, ".info-");
  161.   if (info)
  162.   {
  163.     strcpy(new, fname);
  164.     info = strstr(new, ".info-");
  165.     strcpy(info+2, info+6);
  166.     printf("[ changing %s to %s ]\n", fname, new);
  167.   }
  168.   else
  169.   {
  170.     char *plus = strstr(fname, "++"), *plus2;
  171.     if (plus)
  172.     {
  173.       strcpy(new, fname);
  174.       plus2 = strstr(new, "++");
  175.       strcpy(plus2, "plus");
  176.       strcpy(plus2+4, plus+2);
  177.     }
  178.     else
  179.     {
  180.       printf("  %s %s\n  new name : ", problem, fname);
  181.       gets(new);
  182.     }
  183.   }
  184.   if ((strcmp(new, "") == 0) && (isadir == 2))
  185.     return 0;
  186.   if (isadir) isadir=1;
  187.   ch = (CHANGE *)malloc(sizeof(CHANGE));
  188.   if (ch == 0)
  189.     Fatal("Out of memory");
  190.   ch->next = change_root;
  191.   change_root = ch;
  192.   ch->old = strdup(fname);
  193.   pos = strrchr(fname, '/');
  194.   if (pos && (strchr(new, '/') == 0))
  195.   {
  196.     ch->new = (char *)malloc(strlen(new) + (pos-fname) + 2);
  197.     if (ch->new == 0)
  198.       Fatal("Out of memory");
  199.     *pos = 0;
  200.     sprintf(ch->new, "%s/%s", fname, new);
  201.   }
  202.   else
  203.     ch->new = strdup(new);
  204.   ch->isdir = isadir;
  205.   strcpy(fname, ch->new);
  206.   if (new[0] == 0)
  207.   {
  208.     ch->isdir = 2;
  209.     return 0;
  210.   }
  211.   return 1;
  212. }
  213.  
  214. /*------------------------------------------------------------------------*/
  215.  
  216. void
  217. do_directories(char *n)
  218. {
  219.   char *sl;
  220.   for (sl=n; *sl; sl++)
  221.   {
  222.     if (*sl == '/' || *sl == '\\')
  223.     {
  224.       char save = *sl;
  225.       *sl = 0;
  226.       mkdir (n);
  227.       *sl = save;
  228.     }
  229.   }
  230. }
  231.  
  232. /*------------------------------------------------------------------------*/
  233.  
  234. typedef struct {
  235.   char name[100];
  236.   char operm[8];
  237.   char ouid[8];
  238.   char ogid[8];
  239.   char osize[11];
  240.   char otime[12];
  241.   char ocsum[8];
  242.   char flags[1];
  243.   char filler[356];
  244. } TARREC;
  245.  
  246. char buf[512];
  247.  
  248. tarread(char *fname)
  249. {
  250.   TARREC header;
  251.   int r;
  252.   void *f;
  253.   long perm, uid, gid, size, ftime, csum;
  254.   int dsize;
  255.   char *changed_name;
  256.   long posn=0;
  257.   struct tm tm;
  258.  
  259.   f = oread_open(fname);
  260.  
  261.   while (1)
  262.   {
  263.     oread_read(f, &header);
  264.     if (header.name[0] == 0)
  265.       break;
  266.     sscanf(header.operm, "%lo", &perm);
  267.     sscanf(header.ouid, "%lo", &uid);
  268.     sscanf(header.ogid, "%lo", &gid);
  269.     sscanf(header.osize, "%lo", &size);
  270.     sscanf(header.otime, "%lo", &ftime);
  271.     changed_name = get_entry(header.name);
  272.     if (v_switch)
  273.       printf("%08lx %6lo ", posn, perm);
  274.     else
  275.       printf("%c%c%c%c ",
  276.              perm & 040000 ? 'd' : '-',
  277.              perm & 000400 ? 'r' : '-',
  278.              perm & 000200 ? 'w' : '-',
  279.              perm & 000100 ? 'x' : '-');
  280.     printf("%.20s %9ld %s", ctime(&ftime)+4, size, changed_name);
  281.     if (header.flags[1] == 0x32)
  282.       printf(" -> %s", header.filler);
  283.     printf("\n");
  284.     posn += 512 + (size+511) & ~511;
  285. /*    printf("%6lo %02x %12ld %s\n", perm, header.flags[0], size, changed_name); */
  286.     if (changed_name[strlen(changed_name)-1] == '/')
  287.     {
  288.       changed_name[strlen(changed_name)-1] = 0;
  289.       do {
  290.         r = mkdir(changed_name
  291. #ifdef __GO32__
  292.     ,0
  293. #endif
  294.         );
  295.         if (r && (errno==EACCES))
  296.         {
  297.           change(changed_name, "Duplicate directory name", 2);
  298.           continue;
  299.         }
  300.         if (r)
  301.           r = change(changed_name, "Unable to create directory", 1);
  302.         else
  303.           printf("Making directory %s\n", changed_name);
  304.       } while (r);
  305.     }
  306.     else
  307.     {
  308.     open_file:
  309.       do_directories(changed_name);
  310.       r = open(changed_name, O_WRONLY|O_BINARY|O_CREAT|O_EXCL,
  311.         S_IWRITE|S_IREAD);
  312.       if (r < 0)
  313.         if (change(changed_name, "Cannot exclusively open file", 0))
  314.           goto open_file;
  315.         else
  316.         {
  317.           oread_skip(f, (size+511) & ~511);
  318.         }
  319.       else
  320.       {
  321.         long ftv;
  322.         struct ftime ftimes;
  323.         struct tm *tm;
  324.         while (size)
  325.         {
  326.           if (size < 512)
  327.             dsize = size;
  328.           else
  329.             dsize = 512;
  330.           oread_read(f, buf);
  331.           if (write(r, buf, dsize) < dsize)
  332.           {
  333.             printf("Out of disk space\n");
  334.             exit(1);
  335.           }
  336.           size -= dsize;
  337.         }
  338.         close(r);
  339.         r = open(changed_name, O_RDONLY);
  340.         tm = localtime(&ftime);
  341.         ftimes.ft_tsec = tm->tm_sec / 2;
  342.         ftimes.ft_min = tm->tm_min;
  343.         ftimes.ft_hour = tm->tm_hour;
  344.         ftimes.ft_day = tm->tm_mday;
  345.         ftimes.ft_month = tm->tm_mon+1;
  346.         ftimes.ft_year = tm->tm_year - 80;
  347.         setftime(r, &ftimes);
  348.         close(r);
  349.         if (!(perm & 0200))
  350.           _chmod(changed_name, 1, FA_RDONLY);
  351.       }
  352.     }
  353.   }
  354.   oread_close(f);
  355. }
  356.